/**
 * 
 */
package info.niwota.webime.http;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author qiangli
 * 
 */
public class HttpAdapter implements PI {
	private static HashMap<String, Session> sessions = new HashMap<String, Session>();
	private static final String TAG = "HttpAdapter";
	
	private List<Handler> handlers = new ArrayList<Handler>();

	public HttpAdapter() {
	}

	public List<Handler> getHandlers() {
		return handlers;
	}

	public void addHandler(Handler handler) {
		handlers.add(handler);
	}

	public void setHandlers(List<Handler> handlers) {
		this.handlers = handlers;
	}

	public void service(WebContext ctx, Socket s) {
		Thread th = new Servlet(ctx, s);
		th.setDaemon(true);
		th.start();
	}

	protected class Servlet extends Thread {

		private WebContext ctx = null;

		private Socket sock = null;

		private InputStream in = null;

		private OutputStream out = null;

		public Servlet(WebContext ctx, Socket sock) {
			this.ctx = ctx;
			this.sock = sock;
		}

		public void run() {
			try {
				in = sock.getInputStream();
				out = sock.getOutputStream();
				//
				Request req = new Request();
				Response res = new Response();
				//
				req.parse(in);
				req.webContext = ctx;
				res.setOutputStream(out);
				//
				if (Debug.DEBUG) {
					Log.d(TAG, "***servicing request");
				}
				service(req, res);
				if (Debug.DEBUG) {
					Log.d(TAG, "***closing socket");
				}
				//
				sock.shutdownInput();
				sock.shutdownOutput();
				//
				in.close();
				out.close();
				sock.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		protected void service(Request req, Response res) throws Exception {
			//
			filter(req, res);
			//
			//handle system path
			String p = req.path;
			if (p != null) {
				//help
				//settings
				//logout
				if (p.startsWith("/bin/logout")) {
					Session s = req.session;
					if (s != null) {
						s.authenticated = false;
					}
					res.goHome();
					return;
				}
			}
			
			//custom handlers
			for (Handler h : handlers) {
				if (Debug.DEBUG) {
					Log.d(TAG, h + ": " + req);
				}
				if (h.handle(req, res)) {
					return;
				}
			}

			//
			if (Debug.DEBUG) {
				Log.d(TAG, "no handler available to service this request");
			}
		}

		private void filter(Request req, Response res) throws Exception {
			// check sid
			String sid = scan(req.cookies, "sid");
			Session session = null;
			if (sid == null || ((session = sessions.get(sid)) == null)) {
				session = new Session();
				if (Debug.DEBUG) {
					Log.d(TAG, "filter new session created: " + session.id);
				}
				sessions.put(session.id, session);
			}
			req.session = session;
			res.sid = session.id;
		}

		private String scan(String cookies, String key) {
			if (Utils.isEmpty(cookies)) {
				return null;
			}
			final String[] sa = cookies.split(";");
			final String key_ = key + "=";
			for (int i = 0; i < sa.length; i++) {
				String sai = sa[i].trim();
				if (sai.startsWith(key_)) {
					return sai.substring(key.length() + 1);
				}
			}
			return null;
		}

	}

}
